package com.tma.implementation;

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.tma.model.*;
import com.tma.service.GraphStorageService;

public class GraphManagementService {
	
	//private GraphStorageService m_storageService = new FileBasedStorage();
	private GraphStorageService m_storageService;
	private ArrayList<GraphObject> m_graphs = null;
	private static GraphManagementService instanse = null;
	private static final Logger LOGGER = Logger.getLogger(GraphManagementService.class.getName());
	
	private GraphManagementService(){
		m_storageService = new MongodbBasedStorage("127.0.0.1", 27017);
		
		if(m_graphs == null)
		{
			// Retrieve all existed graph in the file base storage
			m_graphs = m_storageService.retrieveAll();
		}
	}
	
	/**
	 * method: return an singleton instance of Management service
	 * @return
	 */
	public static GraphManagementService getService()
	{
		if(instanse == null){
			instanse = new GraphManagementService();
		}
		return instanse;
	}
	
	/**
	 * method: checking if a graph dose exist
	 * @param graphName
	 * @return -1 if the graph does not exist, otherwise return the graph index in the graps list
	 */
	private int getGraphIndex(String graphName)
	{
		for(int i = 0; i < m_graphs.size(); i++)
		{
			if(m_graphs.get(i).getGraphName().equals(graphName))
			{
				//Graph does exist, return its index in the list.
				return i;
			}
		}
		
		// Graph does not exist.
		return -1;
	}
	
	/**
	 * method: Create a graph and ask the File base to store it.
	 * @param graphName
	 * @param graphDescription
	 * @return true if success otherwise return false
	 */
	public boolean createGraph(String graphName, String graphDescription)
	{
		int graphIndex = getGraphIndex(graphName);
		boolean result = false;
		
		if(graphIndex >= 0) // Graph has already existed
		{
			LOGGER.log(Level.SEVERE, "failed to create a graph due to the graph has already been created: " + graphName);
			result = false;
		}
		else
		{			
			GraphObject graph = new GraphObject(graphName, graphDescription);
			result = m_storageService.store(graph);
			
			if(result == true)
			{
				LOGGER.log(Level.INFO,"graph created:" + graphName);
				m_graphs.add(graph);
			}
			else
			{
				LOGGER.log(Level.SEVERE, "failed to create a graph due to error at FileBasedStorage: " + graphName);
			}
		}
		
		return result;
	}
	
	/**
	 * method: delete a graph and ask the File base to delete it
	 * @param graphName
	 * @return true if success otherwise return false
	 */
	public boolean deleteGraph(String graphName)
	{		
		boolean result = false;
		int graphIndex = getGraphIndex(graphName);
		
		if(graphIndex != -1) // Graph does exist, it's okay to delete
		{
			result = m_storageService.delete(graphName);
			
			if(result == true)
			{
				LOGGER.log(Level.INFO, "graph deleted:" + graphName); 
				m_graphs.remove(graphIndex);
			}
		}
		else // Graph does not exist, cannot delete it
		{
			result = false;
		}
		
		return result;
	}
	
	/**
	 * method: update a graph description and ask the File base to update it.
	 * @param graphName
	 * @param graphDescription
	 * @return true if success otherwise return false
	 */
	public boolean updateGraph(String graphName, String graphDescription)
	{
		int graphIndex = getGraphIndex(graphName);
		if(graphIndex != -1) // graph does exist
		{
			GraphObject graph = m_graphs.get(graphIndex);
			graph.setJsonDescription(graphDescription);
			LOGGER.log(Level.INFO, "graph updated: " + graphName);
			return m_storageService.store(graph);
		}
		else // cannot update non-existed graph
		{
			LOGGER.log(Level.SEVERE, "update graph failed because graph does not exist: " + graphName);
			return false;
		}
	}
	
	/**
	 * method: retrieve a graph from the graphs list
	 * @param graphName
	 * @return
	 */
	public GraphObject getGraph(String graphName)
	{
		int graphIndex = getGraphIndex(graphName);
		if(graphIndex != -1) // graph does exist
		{
			return m_graphs.get(graphIndex);
		}
		else
		{
			return null;
		}
	}
	
	/**
	 * method: retrieve all graphs
	 * @return an ArrayList of graphs
	 */
	public ArrayList<GraphObject> getAllGraph()
	{
		return m_graphs;
	}
	
	/**
	 * @method: delete all graphs
	 * @return true if success otherwise return false
	 */
	public boolean deleteAllGraph()
	{
		boolean result = m_storageService.deleteAll();
		
		if(result == true) // delete ok
		{
			m_graphs.clear();
		}
		else // failed to delete all graphs. we need to resync with the File base
		{
			LOGGER.log(Level.SEVERE, "failed to delete all graphs, try to resync with the File base storage");
			m_graphs.clear();
			
			// Retrieve all existed graph in the file base storage
			m_graphs = m_storageService.retrieveAll();
		}
		
		return result;
	}
}
